package cn.itcast.hotel;

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.Map;

/**
 * @author guozidi  2023-7-30
 * @Description
 * @package cn.itcast.hotel
 */
public class HotelSearchDemo {

    RestHighLevelClient client = null;

    @BeforeEach
    void before() {
        // 0.初始化Client对象
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.200.100:9200"))
        );
    }

    @AfterEach
    void after() throws IOException {
        // .关闭client
        client.close();
    }


    @Test
    void testMatchAll() throws IOException {

        // 2.创建请求对象
        SearchRequest request = new SearchRequest("hotel");

        // 3.组装DSL参数
        request.source().query(QueryBuilders.matchQuery("name","如家"));

        // 3.1 分页
        request.source().from(0).size(3);
        // 3.2 排序
        request.source().sort("price", SortOrder.DESC);
        // 3.3 高亮DSL
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));

        // 1.发送查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.处理结果
        handleResponse(response);
    }

    @Test
    void testMatch() throws IOException {

        // 2.创建请求对象
        SearchRequest request = new SearchRequest("hotel");

        // 3.构建DSL参数
        request.source().query(QueryBuilders.matchQuery("name","上海虹桥如家"));

        // 1.发送查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.解析结果
        handleResponse(response);
    }

    @Test
    void testMultiMatch() throws IOException {

        // 2.创建请求对象
        SearchRequest request = new SearchRequest("hotel");

        // 3.构建DSL参数
        request.source().query(QueryBuilders.multiMatchQuery("上海虹桥如家","name","brand","city"));

        // 1.发送查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.解析结果
        handleResponse(response);
    }


    /**
     * term
     * @throws IOException
     */
    @Test
    void testTermMatch() throws IOException {

        // 2.创建请求对象
        SearchRequest request = new SearchRequest("hotel");

        // 3.构建DSL参数
        request.source().query(QueryBuilders.termQuery("city","上海"));

        // 1.发送查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.解析结果
        handleResponse(response);
    }

    @Test
    void testRange() throws IOException {

        // 2.创建请求对象
        SearchRequest request = new SearchRequest("hotel");

        // 3.构建DSL参数
        request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(150));

        // 1.发送查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4.解析结果
        handleResponse(response);
    }

    @Test
    void testBool() throws IOException {

        // 2.构建请求
        SearchRequest request = new SearchRequest("hotel");

        // 3.1 创建布尔查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 3.2 添加must条件
        boolQueryBuilder.must(QueryBuilders.termQuery("city","上海"));
        // 3.3 添加filter条件
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(100).lte(150));

        // 3.构建DSL参数
        request.source().query(boolQueryBuilder);

        // 1.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        // 4. 处理结果
        handleResponse(response);
    }


    void handleResponse(SearchResponse response){

        // 4.解析结果
        // 4.1 获取外层Hits
        SearchHits hits = response.getHits();
        long total = hits.getTotalHits().value;
        System.out.println("数据总条数"+total);

        // 4.2 获取里层hits
        SearchHit[] innerHits = hits.getHits();
        for (SearchHit innerHit : innerHits) {
            // 解析source
            String sourceAsString = innerHit.getSourceAsString();
            // 解析highlight
            Map<String, HighlightField> highlightFields = innerHit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)){
                HighlightField field = highlightFields.get("name");
                if (field!=null){
                    // 拿到高亮字符串
                    String name = field.getFragments()[0].toString();
                    System.out.println(name);
                }
            }
            System.out.println(sourceAsString);
        }
    }


}
